package cn.buk.tms.eotms.dao;

import cn.buk.common.sc.CommonSearchCriteria;
import cn.buk.common.sc.Page;
import cn.buk.tms.eotms.entity.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import jakarta.transaction.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
@Transactional
public class PnrDaoImpl extends AbstractDao implements PnrDao {

    private static Logger logger = LoggerFactory.getLogger(PnrDaoImpl.class);

    @Override
    public Pnr getPnrById(int id) {

        Pnr pnr = em.find(Pnr.class, id);
        if (pnr != null) {
            em.refresh(pnr);
        }
        return pnr;

    }

    @Override
    public List<Pnr> search(final int ownerId, CommonSearchCriteria sc, String... etermUserNames) {
        List<Pnr> results = null;

        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<Pnr> cq = cb.createQuery(Pnr.class);
        Root<Pnr> root = cq.from(Pnr.class);
        root.alias("o");

        List<Predicate> predicates = new ArrayList<>();

        Predicate predicate = cb.conjunction();
        predicates.add(predicate);

        predicate = cb.equal(root.get(Pnr_.enterpriseId), ownerId);
        predicates.add(predicate);


        if (sc.getPnrNo().length() > 0) {
            predicate = cb.like(root.get(Pnr_.pnrNo), "%" + sc.getPnrNo() + "%");
            predicates.add(predicate);
        }
        if (sc.getEtermUsername() != null && sc.getEtermUsername().length() > 0) {
            predicate = cb.equal(root.get(Pnr_.etermUsername), sc.getEtermUsername());
            predicates.add(predicate);
        }

        if (etermUserNames != null && etermUserNames.length > 0) {
            CriteriaBuilder.In<String> predicate0 = cb.in(root.get(Pnr_.etermUsername));

            for (String username : etermUserNames) {
                predicate0 = predicate0.value(username.toUpperCase());
            }

            predicates.add(predicate0);
        }

        if (sc.getSegStatus() != null && sc.getSegStatus().length() == 2) {
            predicate = cb.equal(root.get(Pnr_.segStatus), sc.getSegStatus());
            predicates.add(predicate);
        }

        if (sc.getDport().length() == 3) {
            predicate = cb.equal(root.get(Pnr_.departurePort), sc.getDport());
            predicates.add(predicate);
        }
        if (sc.getAport().length() == 3) {
            predicate = cb.equal(root.get(Pnr_.arrivalPort), sc.getAport());
            predicates.add(predicate);
        }

        if (sc.getBeginDate() != null) {
            predicate = cb.greaterThanOrEqualTo(root.get(Pnr_.createTime), sc.getBeginDate());
            predicates.add(predicate);
        }

        if (sc.getEndDate() != null) {
            predicate = cb.lessThan(root.get(Pnr_.createTime), sc.getEndDate());
            predicates.add(predicate);
        }

        if (sc.getCarrier() != null && sc.getCarrier().trim().length() == 2) {
            predicate = cb.like(root.get(Pnr_.flightNo), sc.getCarrier() + "%");
            predicates.add(predicate);
        }

        if (sc.getDzStatus() >= 0) {
            predicate = cb.equal(root.get(Pnr_.dzStatus), sc.getDzStatus());
            predicates.add(predicate);
        }


        ////////////////////////
        // count items
        CriteriaQuery<Long> countCq = cb.createQuery(Long.class);
        Root<Pnr> countRoot = countCq.from(Pnr.class);
        countRoot.alias("o");

        countCq.select(cb.count(countRoot)).where(predicates.toArray(new Predicate[predicates.size()]));
        Long count = em.createQuery(countCq).getSingleResult();


        if (count > 0) {
            sc.getPage().setRowCount(count.intValue());

            //search block
            int firstPosition = (sc.getPage().getPageNo() - 1) * sc.getPage().getPageSize();
            cq.select(root).where(predicates.toArray(new Predicate[predicates.size()]));

            List<jakarta.persistence.criteria.Order> orderByes = new ArrayList<>();

            if (sc.getOrderBy() == 1) {
                orderByes.add(cb.desc(root.get("psgCount")));
            } else if (sc.getOrderBy() == 2) {
                orderByes.add(cb.desc(root.get("etermUsername")));
            } else if (sc.getOrderBy() == 3) {
                orderByes.add(cb.desc(root.get("segStatus")));
            } else if (sc.getOrderBy() == 4) {
                orderByes.add(cb.desc(root.get("lastUpdate")));
            }

            orderByes.add(cb.desc(root.get("id")));

            cq.orderBy(orderByes);

            sc.getPage().setRowCount(count.intValue());

            results = em.createQuery(cq)
                    .setFirstResult(firstPosition)
                    .setMaxResults(sc.getPageSize()).getResultList();

        }

        if (results == null) {
            results = new ArrayList<>();
        }
        return results;
    }

    @Override
    public List<TicketSale> searchTprs(final int ownerId, Date beginDate, Date endDate, int deviceId, String ticketNo, CommonSearchCriteria sc, String... etermUserNames) {
        List<TicketSale> results = null;


        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<TicketSale> cq = cb.createQuery(TicketSale.class);
        Root<TicketSale> root = cq.from(TicketSale.class);
        root.alias("o");

        List<Predicate> predicates = new ArrayList<>();

        Predicate predicate = cb.conjunction();
        predicates.add(predicate);

        predicate = cb.equal(root.get(TicketSale_.enterpriseId), ownerId);
        predicates.add(predicate);


        if (beginDate != null && endDate == null) {
            predicate = cb.equal(root.get(TicketSale_.sellDate), beginDate);
            predicates.add(predicate);
        } else if (beginDate == null && endDate != null) {
            predicate = cb.equal(root.get(TicketSale_.sellDate), endDate);
            predicates.add(predicate);
        } else if (beginDate != null && endDate != null) {
            predicate = cb.greaterThanOrEqualTo(root.get(TicketSale_.sellDate), beginDate);
            predicates.add(predicate);

            predicate = cb.lessThanOrEqualTo(root.get(TicketSale_.sellDate), endDate);
            predicates.add(predicate);
        }

        if (deviceId > 0) {
            predicate = cb.equal(root.get(TicketSale_.deviceId), deviceId);
            predicates.add(predicate);
        }

        if (ticketNo != null && ticketNo.trim().length() > 0) {
            predicate = cb.like(root.get(TicketSale_.ticketNo), "%" + ticketNo.trim() + "%");
            predicates.add(predicate);
        }

        if (etermUserNames != null && etermUserNames.length > 0) {
            CriteriaBuilder.In<String> predicate0 = cb.in(root.get(TicketSale_.etermUsername));

            for (String username : etermUserNames) {
                predicate0 = predicate0.value(username.toUpperCase());
            }

            predicates.add(predicate0);
        }

        //计算根据条件查询得出的数据总数
        CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
        Root<TicketSale> countRoot = countQuery.from(TicketSale.class);
        countRoot.alias("o");

        // count items
        countQuery.select(cb.count(countRoot)).where(predicates.toArray(new Predicate[predicates.size()]));
        Long count = em.createQuery(countQuery).getSingleResult();

        //查询
        cq.select(root).where(predicates.toArray(new Predicate[predicates.size()]));

        List<jakarta.persistence.criteria.Order> orderByes = new ArrayList<>();
        if (beginDate == null && endDate == null) {
            orderByes.add(cb.desc(root.get("id")));
        } else {
            orderByes.add(cb.asc(root.get("sellDate")));
            orderByes.add(cb.asc(root.get("deviceId")));
            orderByes.add(cb.asc(root.get("ticketNo")));
        }

        cq.orderBy(orderByes);

        int maxResults = count.intValue();
        if (maxResults > 0) {
            Page page = sc.getPage();
            page.setRowCount(maxResults);
            int i = (page.getPageNo() - 1) * page.getPageSize();

            if (i < 0) {
                i = 0;
            }

            results = em.createQuery(cq)
                    .setFirstResult(i)
                    .setMaxResults(page.getPageSize()).getResultList();
        }

        if (results == null) {
            results = new ArrayList<>();
        }

        return results;
    }

    @Override
    public List<DetrInfo> searchDetrs(int ownerId, CommonSearchCriteria sc, String... etermUserNames) {
        List<DetrInfo> results = null;


        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<DetrInfo> cq = cb.createQuery(DetrInfo.class);
        Root<DetrInfo> root = cq.from(DetrInfo.class);
        root.alias("o");

        List<Predicate> predicates = new ArrayList<>();

        Predicate predicate = cb.conjunction();
        predicates.add(predicate);

        predicate = cb.equal(root.get(DetrInfo_.enterpriseId), ownerId);
        predicates.add(predicate);


        if (etermUserNames != null && etermUserNames.length > 0) {
            CriteriaBuilder.In<String> predicate0 = cb.in(root.get(DetrInfo_.username));

            for (String username : etermUserNames) {
                predicate0 = predicate0.value(username.toUpperCase());
            }

            predicates.add(predicate0);
        }

        //计算根据条件查询得出的数据总数
        CriteriaQuery<Long> countQuery = cb.createQuery(Long.class);
        Root<DetrInfo> countRoot = countQuery.from(DetrInfo.class);
        countRoot.alias("o");

        // count items
        countQuery.select(cb.count(countRoot)).where(predicates.toArray(new Predicate[predicates.size()]));
        Long count = em.createQuery(countQuery).getSingleResult();

        //查询
        cq.select(root).where(predicates.toArray(new Predicate[predicates.size()]));

        List<jakarta.persistence.criteria.Order> orderByes = new ArrayList<>();

        orderByes.add(cb.desc(root.get("id")));


        cq.orderBy(orderByes);

        int maxResults = count.intValue();
        if (maxResults > 0) {
            Page page = sc.getPage();
            page.setRowCount(maxResults);
            int i = (page.getPageNo() - 1) * page.getPageSize();

            if (i < 0) {
                i = 0;
            }

            results = em.createQuery(cq)
                    .setFirstResult(i)
                    .setMaxResults(page.getPageSize()).getResultList();
        }

        if (results == null) {
            results = new ArrayList<>();
        }

        return results;
    }
}
